package com.lyl.myaiagent.agent;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import com.lyl.myaiagent.servertools.tools.registration.ToolRegistration;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.ToolResponseMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.model.tool.ToolCallingManager;
import org.springframework.ai.model.tool.ToolExecutionResult;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.ToolCallbacks;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author lyl
 * @version 1.0
 * @CreateTime: 2025-08-20
 */
@Slf4j
@Data
@EqualsAndHashCode(callSuper = true)
public class ToolCallsAgent extends ReActAgent{

    private final ToolCallback[] allTools;

    private final ToolCallbackProvider toolCallbackProvider;

    private ChatResponse toolCallChatResponse;

    private final ToolCallingManager toolCallingManager;

    private final ChatOptions chatOptions;

    public ToolCallsAgent(ToolCallback[] allTools, ToolCallbackProvider toolCallbackProvider){
        super();
        this.allTools = allTools;
        this.toolCallbackProvider = toolCallbackProvider;
        this.toolCallingManager = ToolCallingManager.builder().build();
        this.chatOptions = DashScopeChatOptions.builder()
                .withProxyToolCalls(true)
                .build();
    }
    @Override
    public boolean think() {
        if(getNextStepPrompt() != null && !getNextStepPrompt().isEmpty()){
            getMessageList().add(new UserMessage(getNextStepPrompt()));
        }
        List<Message> messageList = getMessageList();
        Prompt prompt = new Prompt(messageList, chatOptions);

        try {
            ChatResponse chatResponse = getClient().prompt(prompt)
                    .system(getSystemPrompt())
                    .tools(allTools)
                    .tools(toolCallbackProvider)
                    .call()
                    .chatResponse();

            this.toolCallChatResponse = chatResponse;
            AssistantMessage assistantMessage = chatResponse.getResult().getOutput();
            // 输出助手提示信息
            String result = assistantMessage.getText();
            List<AssistantMessage.ToolCall> toolCalls = assistantMessage.getToolCalls();

            log.info(getName() + "的思考结果：" + result);
            log.info(getName() + "选择了 " + toolCalls.size() + " 个工具来使用");

            String toolCallInfo = toolCalls.stream()
                    .map(toolCall -> String.format("工具名称：%s,参数：%s", toolCall.name(), toolCall.arguments()))
                    .collect(Collectors.joining("\n"));
            log.info(toolCallInfo);

            if(toolCalls.isEmpty()){
                // 如果不调用工具，则记录最后一条记忆信息
                getMessageList().add(assistantMessage);
                return false;
            }else{
                return true;
            }
        } catch (Exception e) {
            log.error(getName() + "在思考的过程中遇到了错误：" + e.getMessage());
            getMessageList().add(new AssistantMessage(getName() + "在思考的过程中遇到了错误：" + e.getMessage()));
            return false;
        }

    }

    @Override
    public String act() {
        if(!toolCallChatResponse.hasToolCalls()){
            return "没有可用工具可以调用";
        }
        // 调用工具
        Prompt prompt = new Prompt(getMessageList(),chatOptions);
        ToolExecutionResult toolExecutionResult = toolCallingManager.executeToolCalls(prompt, toolCallChatResponse);

        // 记录消息上下文
        setMessageList(toolExecutionResult.conversationHistory());

        ToolResponseMessage currentToolMessage =(ToolResponseMessage) CollUtil.getLast(toolExecutionResult.conversationHistory());

        String result = currentToolMessage.getResponses().stream()
                .map(toolResponse -> "工具 " + toolResponse.name() + "完成了它的任务！ 结果为：" + toolResponse.responseData())
                .collect(Collectors.joining("\n"));

        boolean hasTerminate = currentToolMessage.getResponses().stream()
                .anyMatch(toolResponse -> "doTerminate".equals(toolResponse.name()));
        if(hasTerminate){
            setState(AgentState.FINISHED);
        }
        log.info(result);
        return result;
    }
}
